#!/usr/bin/python
#
# Copyright (C) 2008 rambla.be
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
""" @file
@brief Implements RatsService.
"""

try:
  from xml.etree import cElementTree as ElementTree
except ImportError:
  try:
    import cElementTree as ElementTree
  except ImportError:
    from elementtree import ElementTree
import os
import urllib
import atom
import rawsc
import rawsc.service
from rawsc import rats
from rawsc.rats import input, src, job, transc, user, format

SERVER_DEFAULT = "rats.enc01.rambla.be"

class RatsService(rawsc.service.RawsService):
    """ @brief RatsService extends RawsService to provide an interface for RATS requests.
    """

    def __init__(self, username=None, password=None, source=None, server=SERVER_DEFAULT, port = None, additional_headers=None, handler=None):
        super(RatsService, self).__init__(username = username, password = password, source = source, server = server, port = port, additional_headers = additional_headers, handler = handler)

    def delete(self, uri):
        """ Deletes any resource, given the uri. """
        return self.Delete(uri = uri)


    def getInputFeed(self, query = None):
        """ Retrieves an input feed. 
        
            @param query rawsc.Query object that contains queryset args.
            @return InputFeed object
        """
        uri = "/input/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rats.input.InputFeedFromString)

    def getInput(self, uri):
        """ Retrieves an input entry. 
        
            @param uri path (relative or absolute) to the input instance.
            @return InputEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getInput().')
        return self.Get(uri, converter=rats.input.InputEntryFromString)
        
    def createInput(self, name, description=None, base_uri=None, method=None, cdn=None, max_size=None, params=None):
        """ Tries to POST a new input resource to RATS, containing the params that were passed as string args.

            @return InputEntry object
        """
        params = rats.input.InputParams(name=name, description=description, base_uri=base_uri, method=method, cdn=cdn, max_size=max_size, params=params)
        content = rats.input.InputContent(params = params)
        entry = rats.input.InputEntry(content = content)
        return self.Post(entry, uri= "/input/", converter= rats.input.InputEntryFromString)

    def updateInput(self, entry, uri = None):
        """ Update an existing input profile, using a PUT request.
        
            @param entry the complete entry, containing the changed params
            @param uri location of the instance to be updated, if None it will be retrieved from the entry
        """
        if uri is None:
            uri = entry.id.text
        if not uri:
            raise rawsc.RawscException('Entry is not valid.')
        return self.Put(uri = uri, data = entry, converter = rats.input.InputEntryFromString)


    def getFormatFeed(self, query = None):
        """ Retrieves an format feed. 

            @param query rawsc.Query object that contains queryset args.
            @return FormatFeed object
        """
        uri = "/format/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rats.format.FormatFeedFromString)

    def getFormat(self, uri):
        """ Retrieves an format entry. 

            @param uri path (relative or absolute) to the format instance.
            @return FormatEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getFormat().')
        return self.Get(uri, converter=rats.format.FormatEntryFromString)

    def createFormat(self, name, category = "Formats", **kwargs):
        """ Tries to POST a new format resource to RATS, containing the params that were passed as string args.

            @return FormatEntry object
        """
        if category is None:
            category = "formats"
        params = rats.format.FormatParams(name = name, category = category, **kwargs)
        content = rats.format.FormatContent(params = params)
        entry = rats.format.FormatEntry(content = content)
        return self.Post(entry, uri= "/format/", converter= rats.format.FormatEntryFromString)

    def updateFormat(self, entry, uri = None):
        """ Update an existing format profile, using a PUT request.

            @param entry: the complete entry, containing the changed params
            @param uri location of the instance to be updated, if None it will be retrieved from the entry
        """
        if uri is None:
            uri = entry.id.text
        if not uri:
            raise rawsc.RawscException('Entry is not valid.')
        return self.Put(uri = uri, data = entry, converter = rats.format.FormatEntryFromString)



    def getJobFeed(self, query = None):
        """ Retrieves an job feed. 
        
            @param query rawsc.Query object that contains queryset args.
            @return JobFeed object
        """
        uri = "/job/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rats.job.JobFeedFromString)

    def getJob(self, uri):
        """ Retrieves a job entry. 
        
            @param uri path (relative or absolute) to the job instance.
            @return JobEntry object
        """
        if uri is None:
            raise rawsc.RawscException('You must provide a valid URI argument to getJob().')
        return self.Get(uri, converter=rats.job.JobEntryFromString)

    def createJob(self, input=None, output=None, format=None, src_location=None, import_location=None, tgt_location=None, startpos=None, endpos=None, client_passthru=None, client_input=None):
        """ Tries to POST a new input resource to RATS, containing the params that were passed as string args.
        
            Use src_location if the src is already available on the RATS server.
            Use import_location if the src still needs to be imported.

            @return JobEntry object
        """
        params = rats.job.JobParams(input=input, output=output, format=format, src_location=src_location, import_location=import_location, tgt_location=tgt_location, startpos=startpos, endpos=endpos, client_passthru=client_passthru, client_input=client_input)
        content = rats.job.JobContent(params = params)
        entry = rats.job.JobEntry(content = content)
        return self.Post(entry, uri="/job/", converter= rats.job.JobEntryFromString)
        
    

    def getSrcFeed(self, query = None):
        """ Retrieves a src feed. 
        
            @param query rawsc.Query object that contains queryset args.
            @return SrcFeed object
        """
        uri = "/src/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rats.src.SrcFeedFromString)

    def getSrc(self, uri):
        """ Retrieves a src entry. 
        
            @param uri path (relative or absolute) to the src instance.
            @return SrcEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getSrc().')
        return self.Get(uri, converter=rats.src.SrcEntryFromString)

    def createSrc(self, filename, local_path):
        """ Tries to POST a new src resource to RATS.
    
            @param filename filename to be given to the uploaded file on the RATS server.
            @param local_path location of the file to be uploaded on the local machine

            @return SrcEntry object
        """
        media_source = rawsc.MediaSource(file_path = local_path, svr_filename = filename)
        media_entry = self.Post(data = None, uri = '/src/', media_source = media_source, converter=rats.src.SrcEntryFromString)
        return media_entry

    def getSrcFromFilename(self, filename):
        """ Retrieves a src entry from the instance's filename. 
        
            @param filename src instance's filename
            @return SrcEntry object
        """
        uri = "/src/" + str(self.username) + "/" + str(filename) + "/"
        return self.getSrc(uri)

    def deleteSrcFromFilename(self, filename):
        """ Deletes a src instance from the instance's filename. 
        
            @param filename src instance's filename
        """
        uri = "/src/" + str(self.username) + "/" + str(filename) + "/"
        return self.delete(uri)


    def getTranscFeed(self, query = None):
        """ Retrieves a transc feed. 
        
            @param query rawsc.Query object that contains queryset args.
            @return TranscFeed object
        """
        uri = "/transc/"
        if query:
            query.feed = uri
            uri = query.ToUri()
        return self.Get(uri = uri, converter=rats.transc.TranscFeedFromString)

    def getTransc(self, uri):
        """ Retrieves a transc entry. 
        
            @param uri path (relative or absolute) to the transc instance.
            @return TranscEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getTransc().')
        return self.Get(uri, converter=rats.transc.TranscEntryFromString)

    def getTranscFromFilename(self, filename):
        """ Retrieves a transc entry from the instance's filename. 
        
            @param filename transc instance's filename
            @return TranscEntry object
        """
        uri = "/transc/" + str(self.username) + "/" + str(filename) + "/"
        return self.getTransc(uri)

    def deleteTranscFromFilename(self, filename):
        """ Deletes a transc instance from the instance's filename. 
        
            @param filename transc instance's filename
            @return TranscEntry object
        """
        uri = "/transc/" + str(self.username) + "/" + str(filename) + "/"
        return self.delete(uri)
        
    def getTranscFile(self, uri, local_path = None):
        """ Downloads a transc file and (optionally) saves it to a local file location. 
        
            If local_path is given, an attempt is made to save the downloaded file and an exception is thrown in case of failure.
            If local_path is None, the downloaded file is not stored. The caller should store it himself using the file_handle attribute of the returned MediaSource object.
        
            @param uri path (relative or absolute) to the transc media item.
            @param local_path full path, including the filename, to a location where the downloaded file can be stored.
            @return rawsc.MediaSource object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getTranscFile().')
        return self.GetMedia(uri = uri, file_path = local_path)
        
    def getTranscFileFromFilename(self, filename, local_path = None):
        """ Retrieves a transc file from the instance's filename. 

            If local_path is given, an attempt is made to save the downloaded file and an exception is thrown in case of failure.
            If local_path is None, the downloaded file is not stored. The caller should store it himself using the file_handle attribute of the returned MediaSource object.
        
            @param filename transc instance's filename
            @param local_path full path, including the filename, to a location where the downloaded file can be stored.
            @return rawsc.MediaSource object
        """
        uri = "/transc/media/" + str(self.username) + "/" + str(filename) + "/"
        return self.getTranscFile(uri, local_path)

    def getUser(self, uri):
        """ Retrieves an user entry. 

            @param uri path (relative or absolute) to the user instance.
            @return UserEntry object
        """
        if uri is None:
          raise rawsc.RawscException('You must provide a valid URI argument to getUser().')
        return self.Get(uri, converter=rats.user.UserEntryFromString)

    def createUser(self, username, email, first_name=None, last_name=None, password = None):
        params = rats.user.UserParams(username=username, email=email, first_name=first_name, last_name=last_name, password = password)
        content = rats.user.UserContent(params = params)
        entry = rats.user.UserEntry(content = content)
        return self.Post(entry, uri= "/user/", converter= rats.user.UserEntryFromString)

    def updateUser(self, entry, uri = None):
        if uri is None:
            uri = entry.id.text
        if not uri:
            raise rawsc.RawscException('Entry is not valid.')
        return self.Put(uri = uri, data = entry, converter = rats.user.UserEntryFromString)

